from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone
from hosts.models import Host, HostPassword
from hosts.services import PasswordManager, BulkPasswordManager
import logging

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = '管理主机密码的命令行工具'

    def add_arguments(self, parser):
        parser.add_argument(
            'action',
            choices=['change', 'status', 'test', 'bulk-change', 'init'],
            help='要执行的操作'
        )
        parser.add_argument(
            '--host',
            type=str,
            help='主机名或IP地址'
        )
        parser.add_argument(
            '--hosts',
            nargs='+',
            help='多个主机名或IP地址'
        )
        parser.add_argument(
            '--password',
            type=str,
            help='新密码（如果不提供将自动生成）'
        )
        parser.add_argument(
            '--force',
            action='store_true',
            help='强制执行操作'
        )

    def handle(self, *args, **options):
        action = options['action']
        
        if action == 'change':
            self.change_password(options)
        elif action == 'status':
            self.show_status(options)
        elif action == 'test':
            self.test_connection(options)
        elif action == 'bulk-change':
            self.bulk_change_passwords(options)
        elif action == 'init':
            self.initialize_passwords(options)

    def change_password(self, options):
        """修改单个主机密码"""
        host_identifier = options['host']
        if not host_identifier:
            raise CommandError('请指定主机名或IP地址 (--host)')
        
        try:
            # 查找主机
            host = self._find_host(host_identifier)
            if not host:
                raise CommandError(f'找不到主机: {host_identifier}')
            
            # 创建密码管理器
            password_manager = PasswordManager()
            
            # 修改密码
            new_password = options['password']
            success, result_password = password_manager.change_host_password(host, new_password)
            
            if success:
                self.stdout.write(
                    self.style.SUCCESS(
                        f'主机 {host.hostname} 密码修改成功！新密码: {result_password}'
                    )
                )
            else:
                self.stdout.write(
                    self.style.ERROR(
                        f'主机 {host.hostname} 密码修改失败！'
                    )
                )
                
        except Exception as e:
            raise CommandError(f'修改密码时发生错误: {str(e)}')

    def show_status(self, options):
        """显示密码状态"""
        host_identifier = options['host']
        
        if host_identifier:
            # 显示单个主机状态
            host = self._find_host(host_identifier)
            if not host:
                raise CommandError(f'找不到主机: {host_identifier}')
            
            self._display_host_status(host)
        else:
            # 显示所有主机状态
            hosts = Host.objects.all()
            for host in hosts:
                self._display_host_status(host)

    def test_connection(self, options):
        """测试SSH连接"""
        host_identifier = options['host']
        if not host_identifier:
            raise CommandError('请指定主机名或IP地址 (--host)')
        
        try:
            host = self._find_host(host_identifier)
            if not host:
                raise CommandError(f'找不到主机: {host_identifier}')
            
            # 获取当前密码
            try:
                host_password = HostPassword.objects.get(host=host)
                current_password = host_password.get_password()
            except HostPassword.DoesNotExist:
                raise CommandError(f'主机 {host.hostname} 没有密码记录')
            
            # 测试连接
            password_manager = PasswordManager()
            success = password_manager.test_ssh_connection(host, current_password)
            
            if success:
                self.stdout.write(
                    self.style.SUCCESS(
                        f'主机 {host.hostname} SSH连接测试成功！'
                    )
                )
            else:
                self.stdout.write(
                    self.style.ERROR(
                        f'主机 {host.hostname} SSH连接测试失败！'
                    )
                )
                
        except Exception as e:
            raise CommandError(f'测试连接时发生错误: {str(e)}')

    def bulk_change_passwords(self, options):
        """批量修改密码"""
        try:
            bulk_manager = BulkPasswordManager()
            
            if options['hosts']:
                # 根据指定主机列表修改
                host_identifiers = options['hosts']
                host_ids = []
                
                for identifier in host_identifiers:
                    host = self._find_host(identifier)
                    if host:
                        host_ids.append(host.id)
                    else:
                        self.stdout.write(
                            self.style.WARNING(
                                f'找不到主机: {identifier}，跳过'
                            )
                        )
                
                if host_ids:
                    result = bulk_manager.change_passwords_by_hosts(host_ids)
                    self._display_bulk_result(result)
                else:
                    self.stdout.write(self.style.WARNING('没有有效的主机需要修改密码'))
            else:
                # 修改所有过期的密码
                result = bulk_manager.change_all_expired_passwords()
                self._display_bulk_result(result)
                
        except Exception as e:
            raise CommandError(f'批量修改密码时发生错误: {str(e)}')

    def initialize_passwords(self, options):
        """初始化主机密码"""
        try:
            # 获取所有没有密码记录的主机
            hosts_without_password = []
            for host in Host.objects.all():
                if not HostPassword.objects.filter(host=host).exists():
                    hosts_without_password.append(host)
            
            if not hosts_without_password:
                self.stdout.write(self.style.SUCCESS('所有主机都已初始化密码'))
                return
            
            self.stdout.write(f'发现 {len(hosts_without_password)} 台主机需要初始化密码')
            
            if not options['force']:
                confirm = input('是否继续？(y/N): ')
                if confirm.lower() != 'y':
                    self.stdout.write('操作已取消')
                    return
            
            # 初始化密码
            password_manager = PasswordManager()
            success_count = 0
            
            for host in hosts_without_password:
                try:
                    success, new_password = password_manager.change_host_password(host)
                    if success:
                        success_count += 1
                        self.stdout.write(
                            self.style.SUCCESS(
                                f'主机 {host.hostname} 密码初始化成功: {new_password}'
                            )
                        )
                    else:
                        self.stdout.write(
                            self.style.ERROR(
                                f'主机 {host.hostname} 密码初始化失败'
                            )
                        )
                except Exception as e:
                    self.stdout.write(
                        self.style.ERROR(
                            f'主机 {host.hostname} 密码初始化异常: {str(e)}'
                        )
                    )
            
            self.stdout.write(
                self.style.SUCCESS(
                    f'密码初始化完成，成功: {success_count}/{len(hosts_without_password)}'
                )
            )
            
        except Exception as e:
            raise CommandError(f'初始化密码时发生错误: {str(e)}')

    def _find_host(self, identifier):
        """根据主机名或IP地址查找主机"""
        try:
            # 先尝试按主机名查找
            host = Host.objects.get(hostname=identifier)
            return host
        except Host.DoesNotExist:
            try:
                # 再尝试按IP地址查找
                host = Host.objects.get(ip_address=identifier)
                return host
            except Host.DoesNotExist:
                return None

    def _display_host_status(self, host):
        """显示单个主机的密码状态"""
        try:
            host_password = HostPassword.objects.get(host=host)
            status = "过期" if host_password.is_password_expired() else "正常"
            age_hours = host_password.get_password_age()
            next_change = host_password.next_change_time
            
            self.stdout.write(f'\n主机: {host.hostname} ({host.ip_address})')
            self.stdout.write(f'状态: {status}')
            self.stdout.write(f'密码年龄: {age_hours:.1f} 小时')
            self.stdout.write(f'下次修改时间: {next_change}')
            self.stdout.write(f'历史记录数: {len(host_password.password_history)}')
            
        except HostPassword.DoesNotExist:
            self.stdout.write(f'\n主机: {host.hostname} ({host.ip_address})')
            self.stdout.write('状态: 未初始化密码')

    def _display_bulk_result(self, result):
        """显示批量操作结果"""
        self.stdout.write('\n批量操作结果:')
        self.stdout.write(f'成功: {result["success"]}')
        self.stdout.write(f'失败: {result["failed"]}')
        self.stdout.write(f'总计: {result["total"]}')
        
        if result["success"] > 0:
            self.stdout.write(
                self.style.SUCCESS('批量操作完成！')
            )
        else:
            self.stdout.write(
                self.style.WARNING('批量操作完成，但没有成功更新任何密码')
            )
